package cn.sjtu.security.config;


import cn.sjtu.security.filter.JwtCheckFilter;
import cn.sjtu.security.filter.ValidateCodeFilter;
import cn.sjtu.security.handler.AccessDenyHandler;
import cn.sjtu.security.handler.AuthenticationFailedHandler;
import cn.sjtu.security.handler.AuthenticationSuccessfulHandler;
import cn.sjtu.security.handler.LogoutSuccessfulHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.annotation.Resource;

/**
 * 安全配置类
 */
@EnableWebSecurity // 开启安全框架支持
@EnableGlobalMethodSecurity(prePostEnabled = true) // 支持全局方法注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 密码加密器
    @Autowired
    PasswordEncoder passwordEncoder;

    // 认证成功处理器
    @Autowired
    private AuthenticationSuccessfulHandler authenticationSuccessfulHandler;

    // 认证失败处理器
    @Autowired
    private AuthenticationFailedHandler authenticationFailedHandler;

    // 登出成功处理器
    @Autowired
    private LogoutSuccessfulHandler logoutSuccessfulHandler;

    // 访问拒绝处理器
    @Autowired
    private AccessDenyHandler accessDenyHandler;

    // 验证验证码过滤器
    @Resource
    private ValidateCodeFilter validateCodeFilter;

    // 验证jwt过滤器
    @Resource
    private JwtCheckFilter jwtCheckFilter;


//    @Bean
//    @Order(0)
//    public UserDetailsService userDetailsService () {
//        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        UserDetails syo = User.withUsername("syo").password(passwordEncoder.encode("123456")).authorities("world").build();
//        manager.createUser(syo);
//        return manager;
//    }

    /**
     * 授权配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 关闭跨域请求保护
        http.csrf().disable();

        http.authorizeRequests().mvcMatchers("/").permitAll(); // 允许任何人任何权限访问 /
        http.authorizeRequests().mvcMatchers("/code/image").permitAll(); // 任何人可访问二维码生成地址
        http.authorizeRequests().antMatchers("/css/**", "/font/**", "/image/**", "/js/**", "/picture/**")
                .permitAll(); // 放开静态资源

        // 可在这儿控制接口访问权限，不过这里已经移动至全局方法权限控制上去了
        // http.authorizeRequests().mvcMatchers("/hello1").hasAuthority("p1");
        // http.authorizeRequests().mvcMatchers("/hello2").hasAuthority("p2");

        http.authorizeRequests().antMatchers("/login").permitAll(); // 登录页面全面放开
        http.authorizeRequests().anyRequest().authenticated(); // 其他地址需要登录甚至需要权限

        // 认证成功处理器successHandler和页面defaultSuccessUrl不能同时存在，谁定义在后面执行谁
        http.formLogin()
                .usernameParameter("username") // 设定模板字段
                .passwordParameter("password") // 同样设置模板字段
                .loginPage("/login") // 登录页面
                .successHandler(authenticationSuccessfulHandler)
                // .defaultSuccessUrl("/index") // 成功跳转的地址
                .loginProcessingUrl("/doLogin") // action请求处理的地址
                //.failureHandler(authenticationFailed) // 失败处理器
        ;

        // 默认的登出地址为 /logout
        http.logout().logoutSuccessHandler(logoutSuccessfulHandler); // 登出成功处理器


        // http.exceptionHandling().accessDeniedHandler(accessDenyHandler); // 访问拒绝处理器

        // 添加验证码验证过滤器
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);

        // 添加验证jwt过滤器
        http.addFilterBefore(jwtCheckFilter, UsernamePasswordAuthenticationFilter.class);

        // 关闭框架自带的基于session保存认证的方式
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    /**
     * 密码加密器
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
